package com.atwisdom.star.core.bsl.basicClass.impl;

import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.actionType.basicClass.MeshLibActionType;
import com.atwisdom.star.common.util.FileUtil;
import com.atwisdom.star.common.vo.*;
import com.atwisdom.star.core.bsl.basicClass.MeshLibBslService;
import com.atwisdom.star.core.dao.pojo.basicClass.MeshLib;
import com.atwisdom.star.core.dsl.basicClass.MeshLibDslService;
import com.atwisdom.star.exception.pojo.BusinessException;
import org.apache.commons.lang.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.List;

@Service
public class MeshLibBslServiceImpl implements MeshLibBslService {

    @Value("${filePath}")
    private String baseFilePath;

    private MeshLibDslService meshLibDslService;

    @Autowired
    public void setMeshLibDslService(MeshLibDslService meshLibDslService) {
        this.meshLibDslService = meshLibDslService;
    }

    /**
     * 服务工厂方法
     * @param actionDataList 参数
     * @return 参数
     * @throws BusinessException 异常
     */
    @Transactional
    public ResultInfo<?> responseFactory(List<ActionData<JSONObject>> actionDataList) throws BusinessException {
        ResultInfo<?> resultInfo = null;
        for (ActionData<JSONObject> actionData : actionDataList) {
            String action = actionData.getAction();
            MeshLibActionType actionType = MeshLibActionType.valueOf(action);
            String methodName = actionType.getMethodName();
            resultInfo = this.execMethod(methodName, actionData);
        }
        return resultInfo;
    }

    /**
     * 反射执行业务单元方法
     *
     * @param methodName 方法名
     * @param actionData 方法参数
     * @return 返回结果
     * @throws BusinessException 业务异常
     */
    public ResultInfo<?> execMethod(String methodName, ActionData<JSONObject> actionData) throws BusinessException {
        Class<? extends MeshLibBslServiceImpl> clz = this.getClass();
        try {
            Method method = clz.getMethod(methodName, ActionData.class);
            MeshLibBslServiceImpl service = (MeshLibBslServiceImpl) AopContext.currentProxy();
            return (ResultInfo<?>) method.invoke(service, actionData);
        } catch (NoSuchMethodException ex) {
            throw new BusinessException("999999", "没有找到该方法(" + methodName + ")", ex);
        } catch (IllegalAccessException ex) {
            throw new BusinessException("999999", "没有访问该方法权限(" + methodName + ")", ex);
        } catch (InvocationTargetException ex) {
            Throwable targetException = ex.getTargetException();
            if (targetException instanceof BusinessException) {
                BusinessException bex = (BusinessException) targetException;
                throw new BusinessException("999999", bex.getErrorMsg(), ex);
            } else {
                throw new BusinessException("999999", "出错了请重试：(" + methodName + ")---" + ex.getMessage(), ex);
            }
        }
    }


    @Override
    public ResultInfo<?> add(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        JSONObject jsonObject = data.get(0);
        JSONObject addJsonObject = this.meshLibDslService.add(jsonObject);
        return JsonResult.success(addJsonObject);
    }

    @Override
    public ResultInfo<?> batchAdd(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        List<JSONObject> addJsonObject = this.meshLibDslService.batchAdd(data);
        return JsonResult.success(addJsonObject);
    }

    @Override
    public ResultInfo<?> update(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        JSONObject jsonObject = data.get(0);
        JSONObject addJsonObject = this.meshLibDslService.update(jsonObject);
        return JsonResult.success(addJsonObject);
    }

    @Override
    public ResultInfo<?> batchUpdate(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        List<JSONObject> addJsonObject = this.meshLibDslService.batchUpdate(data);
        return JsonResult.success(addJsonObject);
    }

    @Override
    public ResultInfo<?> deleteByIds(ActionData<JSONObject> actionData) {
        this.meshLibDslService.deleteByIds(actionData.getIds());
        return JsonResult.success(StatusCode.SUCCESS);
    }

    @Override
    public ResultInfo<?> query(ActionData<JSONObject> actionData) {
        String condition = actionData.getCondition();
        String orderBy = actionData.getOrderBy();
        List<JSONObject> query = this.meshLibDslService.query(condition, orderBy);
        return JsonResult.success(query);
    }

    @Override
    public ResultInfo<?> queryInfo(ActionData<JSONObject> actionData) {
        String condition = actionData.getCondition();
        String orderBy = actionData.getOrderBy();
        List<JSONObject> query = this.meshLibDslService.queryInfo(condition, orderBy);
        return JsonResult.success(query);
    }

    @Override
    public ResultInfo<?> queryByIds(ActionData<JSONObject> actionData) {
        List<JSONObject> query = this.meshLibDslService.queryByIds(actionData.getIds());
        return JsonResult.success(query);
    }

    @Override
    public ResultInfo<?> queryByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String condition = actionData.getCondition();
        String orderBy = actionData.getOrderBy();
        PageInfo pageInfo = this.meshLibDslService.queryByPage(pageNumber, pageSize, condition, orderBy);
        return JsonResult.success(pageInfo);
    }

    @Override
    public ResultInfo<?> queryInfoByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String condition = actionData.getCondition();
        String orderBy = actionData.getOrderBy();
        PageInfo pageInfo = this.meshLibDslService.queryInfoByPage(pageNumber, pageSize, condition, orderBy);
        return JsonResult.success(pageInfo);
    }
    @Override
    public ResultInfo<?> uploadFile(MultipartFile file, Long id) throws BusinessException {
        if (file.isEmpty()) {
            throw new BusinessException("999999", "上传文件信息为空，操作失败！");
        }
        try {
            String fileName = file.getOriginalFilename();
            String preName = fileName.substring(0,fileName.lastIndexOf("."));
            String suffixName = fileName.substring(fileName.lastIndexOf(".")+1);

            Date current = new Date();
            SimpleDateFormat simpleDate = new SimpleDateFormat("yyyyMMdd");
            String strDate = simpleDate.format(current);
            String filePath = baseFilePath + strDate + "/";
            String path = filePath + fileName;
            File dest = new File(new File(path).getAbsolutePath());
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }

            file.transferTo(dest);
            MeshLib meshLib = this.meshLibDslService.queryById(id);
            meshLib.setFileName(path);
            meshLib.setDisplayFileName(preName);
            meshLib.setExtendName(suffixName);
            JSONObject meshJson = this.meshLibDslService.updateById(meshLib);
            return JsonResult.success(meshJson);
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new BusinessException("999999", "上传文件失败！", ex);
        }
    }
    @Override
    public ResultInfo<?> downloadFileBase64ByName(ActionData<JSONObject> actionData) throws BusinessException {
        String name = actionData.getName();
        MeshLib meshLib = this.meshLibDslService.queryByName(name);
        if(meshLib==null){
            return JsonResult.error(500,"数据不存在，下载文件失败");
        }

        String fileName = meshLib.getFileName();
        if (StringUtils.isNotBlank(fileName)) {
            String base64;
            InputStream in = null;
            try {
                File file = new File(fileName);
                in = new FileInputStream(file);
                byte[] bytes = new byte[(int) file.length()];
                in.read(bytes);
                base64 = Base64.getEncoder().encodeToString(bytes);
            } catch (Exception e) {
                e.printStackTrace();
                throw new BusinessException("999999", "下载文件失败！", e);
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                        throw new BusinessException("999999", "下载文件失败！", e);
                    }
                }
            }
            return JsonResult.success(base64);
        }
        return JsonResult.error(StatusCode.ERROR_DOWNLOAD_FILE);
    }

    @Override
    public ResultInfo<?> downloadFileBase64ById(ActionData<JSONObject> actionData) throws BusinessException {
        Long id = actionData.getId();
        MeshLib meshLib = this.meshLibDslService.queryById(id);
        String fileName = meshLib.getFileName();
        if (StringUtils.isNotBlank(fileName)) {
            String base64;
            InputStream in = null;
            try {
                File file = new File(fileName);
                in = new FileInputStream(file);
                byte[] bytes = new byte[(int) file.length()];
                in.read(bytes);
                base64 = Base64.getEncoder().encodeToString(bytes);
            } catch (Exception e) {
                e.printStackTrace();
                throw new BusinessException("999999", "下载文件失败！", e);
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                        throw new BusinessException("999999", "下载文件失败！", e);
                    }
                }
            }
            return JsonResult.success(base64);
        }
        return JsonResult.error(StatusCode.ERROR_DOWNLOAD_FILE);
    }

    @Override
    public void downloadFileById(ActionData<JSONObject> actionData, HttpServletResponse response, HttpServletRequest request) throws BusinessException {
        Long id = actionData.getId();
        MeshLib meshLib = this.meshLibDslService.queryById(id);
        String fileName = meshLib.getFileName();
        if (StringUtils.isNotBlank(fileName)) {
            try {
                String realFileName = meshLib.getDisplayFileName()+"."+meshLib.getExtendName();
                response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
                FileUtil.setAttachmentResponseHeader(response, realFileName);
                FileUtil.writeBytes(fileName, response.getOutputStream());
            } catch (Exception e) {
                throw new BusinessException("999999", "下载文件失败！", e);
            }
        }
    }

    @Override
    public void downloadFileByName(ActionData<JSONObject> actionData, HttpServletResponse response, HttpServletRequest request) throws BusinessException {
        String name = actionData.getName();
        MeshLib meshLib = this.meshLibDslService.queryByName(name);
        if(meshLib==null){
            throw new BusinessException("999999", "数据不存在,下载文件失败！");
        }
        String fileName = meshLib.getFileName();
        if (StringUtils.isNotBlank(fileName)) {
            try {
                String realFileName = meshLib.getDisplayFileName()+"."+meshLib.getExtendName();
                response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
                FileUtil.setAttachmentResponseHeader(response, realFileName);
                FileUtil.writeBytes(fileName, response.getOutputStream());
            } catch (Exception e) {
                throw new BusinessException("999999", "下载文件失败！", e);
            }
        }
    }

    @Override
    public ResultInfo<?> deleteFileById(ActionData<JSONObject> actionData) throws BusinessException {
        Long id = actionData.getId();
        MeshLib meshLib = this.meshLibDslService.queryById(id);
        String fileName = meshLib.getFileName();
        boolean deleteFlag = FileUtil.deleteFile(fileName);
        if (deleteFlag) {
            this.meshLibDslService.deleteById(id);
            return JsonResult.success("文件删除成功");
        } else {
            return JsonResult.error(StatusCode.RUN_ERROR.getCode(), "文件删除失败");
        }
    }

    @Override
    public ResultInfo<?> deleteFileByName(ActionData<JSONObject> actionData) throws BusinessException {
        String name = actionData.getName();
        MeshLib meshLib = this.meshLibDslService.queryByName(name);
        String fileName = meshLib.getFileName();
        boolean deleteFlag = FileUtil.deleteFile(fileName);
        if (deleteFlag) {
            Long id = meshLib.getId();
            this.meshLibDslService.deleteById(id);
            return JsonResult.success("文件删除成功");
        } else {
            return JsonResult.error(StatusCode.RUN_ERROR.getCode(), "文件删除失败");
        }
    }
}
